﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using WenSkin.DLL;
using WenSkin.Json;
using WenSkin.Json.Linq;

namespace WenSkin.WenJsonConfig
{
    public class JsonConfig
    {
        public JsonConfig() : this("WenAutoConfig")
        {
        }
        public JsonConfig(string jsonFileName)
        {
            Path = Application.StartupPath;
            JsonFileName = jsonFileName;
            Load();
        }
        
        public JsonConfig(string path,string jsonFileName)
        {
            this.Path = path;
            JsonFileName = jsonFileName;
            Load();
        }

        #region 私有属性
        private JsonConfigGroupList groups;
        #endregion

        #region 公有属性
        public string JsonFileName { get;private set; }
        public string Path { get;private set; }
        public JsonConfigGroupList Groups => groups ??= new JsonConfigGroupList();
        public JsonConfigGroup this[string str] => Groups[str];
        public string this[string group, string val] { get => Groups[group, val]; set => Groups[group, val] = value; }
        #endregion

        //打开配置文件
        public void Load()
        {
            string path = $"{this.Path}\\{JsonFileName}.json";
            Load(path);
        }
        public void Load(string path)
        {
            if (!File.Exists(path))
                Save();
            string str = File.ReadAllText(path);
            groups = JsonConvert.DeserializeObject<JsonConfigGroupList>(str);

            //将加密数据解密
            Enc(groups);

            void Enc(JsonConfigGroupList groups)
            {
                foreach (var g in groups)
                {
                    if (g.Groups.Count > 0)
                        Enc(g.Groups);
                    foreach (var item in g.Items)
                    {
                        if (item.Ecc)
                        {
                            item.Value = item.Value?.ToAESDecrypt();
                        }
                    }
                }
            }
        }
        //保存文件
        public void Save()
        {
            string path = $"{this.Path}\\{JsonFileName}.json";
            Save(path);
        }
        public void Save(string path)
        {
            var js = new JsonConfigGroupList();

            //加密存储数据
            OutData(this.Groups, js);

            static void OutData(JsonConfigGroupList groups, JsonConfigGroupList owner)
            {
                foreach (var g in groups)
                {
                    JsonConfigGroup jsonConfigGroup = new JsonConfigGroup(owner)
                    {
                        Name = g.Name,
                        AllowAdd = g.AllowAdd,
                        Info = g.Info,
                        Visible = g.Visible,
                    };
                    owner.Add(jsonConfigGroup);

                    foreach (var item in g.Items)
                    {
                        JsonConfigItem jsonConfigItem = new JsonConfigItem(jsonConfigGroup.Items)
                        {
                            ComboBox = item.ComboBox,
                            Delete = item.Delete,
                            Info = item.Info,
                            Name = item.Name,
                            ReadOnly = item.ReadOnly,
                            Visible = item.Visible,
                            Tip = item.Tip,
                            Ecc = item.Ecc,
                        };
                        jsonConfigItem.Items.AddRange(item.Items.ToArray());

                        if (item.Ecc)
                        {
                            jsonConfigItem.Value = item.Value?.ToAESEncrypt();
                        }
                        else
                            jsonConfigItem.Value = item.Value;
                        jsonConfigGroup.Items.Add(jsonConfigItem);
                    }

                    if (g.Groups.Count > 0)
                        OutData(g.Groups, jsonConfigGroup.Groups);
                }
            }

            var json = JsonConvert.SerializeObject(js, Formatting.Indented);

            if (!Directory.Exists(System.IO.Path.GetDirectoryName(path)))
                Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path));
            File.WriteAllText(path, json);
        }

        public void Show()
        {
            new WenConfigForm(this).Show();
        } 
        public void ShowDialog()
        {
            new WenConfigForm(this).ShowDialog();
        }

        public class JsonConfigGroupList : List<JsonConfigGroup>
        {
            public JsonConfigGroup this[string str] => Find(a => a.Name.ToUpper() == str.ToUpper());

            public string this[string group, string val]
            {
                get => Find(a => a.Name.ToUpper() == group.ToUpper())?.Items.Find(a => a.Name.ToUpper() == val.ToUpper())?.Value;
                set
                {
                    if (Find(a => a.Name.ToUpper() == group.ToUpper()) is JsonConfigGroup item && item.Items.Find(a => a.Name.ToUpper() == val.ToUpper()) is JsonConfigItem im)
                    {
                        im.Value = value;
                    }                 
                }
            }

            /// <summary>
            /// 新增组
            /// </summary>
            /// <param name="groupName">名称</param>
            /// <param name="info">描述</param>
            /// <param name="add">若存在是否继续新增</param>
            /// <returns></returns>
            public JsonConfigGroup Add(string groupName, string info = "组", bool add = false)
            {
                if (Find(a => a.Name == groupName) is JsonConfigGroup group && !add)
                {
                    return group;
                }
                else
                {
                    group = new JsonConfigGroup(this)
                    {
                        Name = groupName,
                        Info = info
                    };
                    Add(group);
                    return group;
                }
            }
        }

        public class JsonConfigGroup
        {
            private JsonConfigGroupList groups;
            private JsonConfigItemList items;
            private readonly JsonConfigGroupList owner;

            public JsonConfigGroup(JsonConfigGroupList owner)
            {
                this.owner = owner;
                Name = "";
                Info = "";
                AllowAdd = false;
                Visible = true;
            }

            public string Name { get; set; }
            public string Info { get; set; }
            public bool AllowAdd { get; set; }
            public bool Visible { get; set; }
            public JsonConfigItemList Items => items ??= new JsonConfigItemList();
            public JsonConfigGroupList Groups => groups ??= new JsonConfigGroupList();

            public void Remove()
            {
                owner.Remove(this);                
            }
        }

        public class JsonConfigItem
        {
            private List<string> items;
            private readonly JsonConfigItemList owner;

            public JsonConfigItem(JsonConfigItemList owner)
            {
                this.owner = owner;
                Name = "";
                Info = "";
                Ecc = false;
                ReadOnly = false;
                Delete = false;
                Value = "";
                Tip = "";
                Visible = true;
            }

            public string Name { get; set; }
            public string Info { get; set; }
            public bool Ecc { get; set; }
            public bool ReadOnly { get; set; }
            public bool Delete { get; set; }
            public string Value { get; set; }
            public string Tip { get; set; }
            public bool Visible { get; set; }
            public bool ComboBox { get; set; }
            public List<string> Items => items ??= new List<string>();
            public void Remove()
            {
                owner.Remove(this);
            }
        }

        public class JsonConfigItemList : List<JsonConfigItem>
        {
            public JsonConfigItemList()
            {
            }
            public JsonConfigItem this[string str] => Find(a => a.Name.ToUpper() == str.ToUpper());

            public JsonConfigItem Add(string itemName,string value,string info="项",bool ecc=false,bool readOnly=false)
            {
                JsonConfigItem item = new JsonConfigItem(this)
                {
                    Name = itemName,
                    Info = info,
                    Ecc = ecc,
                    ReadOnly = readOnly,
                    Value = value,
                };
                this.Add(item);
                return item;
            }
        }
    }
}
